package com.restkeeper.utils;

import cn.hutool.core.net.URLDecoder;
import org.apache.commons.codec.binary.Hex;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public class Sha256Util {

    public static final String ALGORITHM = "AES";
    public static final String SECRET_AES_ECB_MODE = "ECB";
    public static final String SECRET_AES_PKCS5_PADDING = "PKCS5Padding";

    /***
     * 利用Apache的工具类实现SHA-256加密
     *
     * @param str 加密的报文
     * @return String
     */
    public static String getSHA256Str(String str) {
        MessageDigest messageDigest;
        String encodeStr = "";
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
            byte[] hash = messageDigest.digest(str.getBytes(StandardCharsets.UTF_8));
            encodeStr = Hex.encodeHexString(hash);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return encodeStr;
    }

    /**
     * 解密
     *
     * <p>
     * byte[] -> byte[]
     *
     * @param mode       模式
     * @param padding    填充
     * @param key        密钥
     * @param iv         向量，如果模式不用向量，可传递null
     * @param ciphertext 密文
     * @return 明文
     */
    public static byte[] decrypt(String mode, String padding, byte[] key, byte[] iv, byte[] ciphertext) {
        return doBytes(mode, padding, key, iv, ciphertext, Cipher.DECRYPT_MODE);
    }

    private static byte[] doBytes(String mode, String padding, byte[] key, byte[] iv, byte[] input, int opMode) {
        Cipher cipher = createCipher(mode, padding, key, iv, opMode);
        try {
            byte[] output = cipher.doFinal(input);
            return output;
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            throw new RuntimeException(e);
        }
    }

    private static Cipher createCipher(String mode, String padding, byte[] key, byte[] iv, int opMode) {
        SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM);
        IvParameterSpec ivSpec = null;
        if (iv != null) {
            ivSpec = new IvParameterSpec(iv);
        }

        String transformation = ALGORITHM + "/" + mode + "/" + padding;
        Cipher cipher;
        try {
            cipher = Cipher.getInstance(transformation);
            cipher.init(opMode, keySpec, ivSpec);
            return cipher;
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException |
                 InvalidAlgorithmParameterException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {

        // 原始价格，单位为分
        String price = "1000";

        // 聚合广告位 Security Key
        String secretKey = "p5iqg48gzguw25gcy2hbp04xkbcffm4b";



        // 平台使用上述key，对price加密、base64 encode、url encode之后得到的加密价格串
//        String encryptedPrice = "1CIoSLK1Ye2SAAgNB5kiYQ%3D%3D";
        String encryptedPrice = "7b08efd1-1ce7-4386-b7ae-53282778f52e";
        decode(encryptedPrice,secretKey);
//        // 原始价格，单位为分
//        String price = "1000";
//
//        // 聚合广告位 Security Key
//        String secretKey = "xm3k88pem11a5cdg7gqn8agoxnh328m9";
//
//        // 平台使用上述key，对price加密、base64 encode、url encode之后得到的加密价格串
//        String encryptedPrice = "1CIoSLK1Ye2SAAgNB5kiYQ%3D%3D";

        // 首先对收到的加密字符串进行 URL decode
        String decodedString = URLDecoder.decode(encryptedPrice, StandardCharsets.UTF_8);

        // 再对URL decode 之后的价格进行Base64 decode
        byte[] encryptedBytes = Base64.getDecoder().decode(decodedString.getBytes());

        // 进行解密
        byte[] decryptedBytes = decrypt(SECRET_AES_ECB_MODE, SECRET_AES_PKCS5_PADDING, secretKey.getBytes(),
                null, encryptedBytes);

        String decryptedPrice = new String(decryptedBytes);

        // 解密后，价格应该等于1000
        System.out.println(price.equals(decryptedPrice));
    }

    /**
     * 解密
     * @param securityKey 聚合广告位 Security Key
     * @param encrypted    加密串
     * @return 明文
     */
    public static String decode(String encrypted,String securityKey) {
        String signString = securityKey + ":" + encrypted;
        String sha256Str = Sha256Util.getSHA256Str(signString);
//        String decodedString=getSHA256Str(securityKey+":"+encrypted);
        // 首先对收到的加密字符串进行 URL decode
         String encryptedString = URLDecoder.decode(sha256Str, StandardCharsets.UTF_8);

        // 再对URL decode 之后的价格进行Base64 decode
        byte[] encryptedBytes = Base64.getDecoder().decode(encryptedString.getBytes());

        // 进行解密
        byte[] decryptedBytes = decrypt(SECRET_AES_ECB_MODE, SECRET_AES_PKCS5_PADDING, securityKey.getBytes(),
                null, encryptedBytes);

        return new String(decryptedBytes);
    }


}
